import {
	useState,
	useEffect,
	useRef,
	useCallback,
	type FC,
	type ReactNode,
} from "react";

/**
 * 懒加载图片组件
 * @param src 图片地址
 * @param placeholder 占位符
 * @param alt 图片alt
 * @param className 图片样式
 * @param lazyLoadThreshold 懒加载阈值 单位px
 * @param onLoad 图片加载完成回调
 * @param onerror 图片加载失败回调
 * @returns
 */
const LazyLoadImage: FC<{
	src: string;
	placeholder?: ReactNode;
	alt?: string;
	className?: string;
	lazyLoadThreshold?: number;
	onLoad?: () => void;
	onerror?: () => void;
}> = ({
	src,
	placeholder,
	alt,
	className,
	lazyLoadThreshold = 200,
	onLoad,
	onerror,
}) => {
	const [imageSrc, setImageSrc] = useState("");
	const imgRef = useRef<HTMLImageElement>(null);
	const observerRef = useRef<IntersectionObserver | null>(null);

	// 处理图片加载
	const handleLoad = useCallback(() => {
		onLoad?.();
	}, [onLoad]);

	// 处理图片加载失败
	const handleError = useCallback(() => {
		onerror?.();
	}, [onerror]);

	useEffect(() => {
		// 初始化IntersectionObserver
		observerRef.current = new IntersectionObserver(
			(entries) => {
				entries.forEach((entry) => {
					if (entry.isIntersecting && imgRef.current && !imageSrc) {
						// 图片进入视口且未加载，则开始加载
						setImageSrc(src);
						observerRef.current?.unobserve(imgRef.current);
					}
				});
			},
			{
				rootMargin: `${lazyLoadThreshold}px 0px`, // 提前lazyLoadThreshold px开始加载
				threshold: 0.1,
			}
		);

		const currentImg = imgRef.current;
		if (currentImg) {
			observerRef.current.observe(currentImg);
		}

		// 清理函数
		return () => {
			if (currentImg && observerRef.current) {
				observerRef.current.unobserve(currentImg);
			}
		};
	}, [src, imageSrc, lazyLoadThreshold]);

	return (
		<div
			className={`relative ${className}`}
			style={{ width: "100%", height: "100%" }}>
			{/* 占位符 */}
			{!imageSrc && (
				<div className="absolute inset-0 flex items-center justify-center bg-gray-100">
					{placeholder}
				</div>
			)}

			{/* 图片元素 */}
			<img
				ref={imgRef}
				src={imageSrc}
				alt={alt}
				onLoad={handleLoad}
				onError={handleError}
				style={{
					opacity: imageSrc ? 1 : 0,
					width: "100%",
					height: "100%",
					objectFit: "cover",
				}}
			/>
		</div>
	);
};

export default LazyLoadImage;
